<template>
<div :class="[$style.container]">
  <div :class="[$style.search]">
    <el-input v-model="keyword" prefix-icon="el-icon-search" placeholder="请输入团队或成员" clearable @input="onSearch"></el-input>
  </div>
  <div :class="[$style.body]">
    <el-tree :load="loadFn" lazy :class="[$style.tree]" :props="defaultProps"
      @check-change="onCheckedChange" node-key="_nodeKey"
      highlight-current ref="tree" show-checkbox check-strictly v-show="!keyword">
      <template v-slot="{node}">
        <div :class="[$style.item]">
          <span :class="[$style.text]">
            <span class="ft-lg">
              <i class="el-icon-s-management" v-if="node.data.type === 'team'"></i>
              <i class="el-icon-s-custom" v-else></i>
            </span>
            <span class="ml-2">{{label(node)}}</span>
          </span>
          <span :class="[$style.action]"  @click.stop="onAdd(node.data)">
            <span v-if="node.data.type === 'team'">
              <el-link :underline="false" type="info" class="mr-1" title="全选" @click.stop="onSelectedAll(node, true)">
                <span class="ft-18"><svg-icon icon="select-all"></svg-icon></span>
              </el-link>
              <el-link :underline="false" type="info" class="mr-1" title="取消选择" @click.stop="onSelectedAll(node, false)">
              <span class="ft-18"><svg-icon icon="unselected"></svg-icon></span>
            </el-link>
            </span>
            <el-link :underline="false" type="info">
              <span class="ft-18"><i class="el-icon-circle-plus-outline"></i></span>
            </el-link>
          </span>
        </div>
      </template>
    </el-tree>
    <div :class="[$style.filterWrap]" v-show="keyword" v-loading="filtering">
      <ul :class="[$style.list]" v-if="filterData.length > 0 && !filtering">
        <li :class="[$style.listItem]" v-for="(row, i) in filterData" :key="i">
          <span :class="[$style.text]">
            <span class="ft-lg">
              <i class="el-icon-s-management" v-if="row.type === 'team'"></i>
              <i class="el-icon-s-custom" v-else></i>
            </span>
            <span class="ml-2"><highlight-text :text="row.label" :keyword="keyword"></highlight-text></span>
          </span>
          <span :class="[$style.action]" @click.stop="onAdd(row)">
            <el-link :underline="false" type="info">
              <span class="ft-18"><i class="el-icon-circle-plus-outline"></i></span>
            </el-link>
          </span>
        </li>
      </ul>
      <empty-data v-if="filterData.length < 1 && !filtering">无符合条件记录</empty-data>
    </div>
  </div>
</div>
</template>

<script lang="ts">

import { Vue, Component, Prop, Emit, Ref, Watch } from 'vue-property-decorator'
import { debounce } from '@/utils/perf'
import { queryRootTeams, queryTeamsByParent, searchTeams } from '@/api/team'
import { queryUsersByTeam } from '@/api/team-user'
import { searchEntUsers } from '@/api/ent-user'
import { AppModule } from '@/store'

@Component
export default class TeamAndMemberTree extends Vue {
  @Emit() add (value: any) {}

  @AppModule.State currentSpace!: any

  @Prop() checkedRows!: any[]

  @Emit('update:checkedRows') updateCheckedRows (value: any[]) {}

  keyword = ''

  filtering = false

  filterData: any[] = []

  defaultProps = {
    label: 'label',
    isLeaf: 'leaf'
  }

  localCheckedRows: any = []

  serachDelayFn!: (keyword: string) => void

  setCheckRows (rows = []) {
    this.localCheckedRows = rows
    this.updateCheckedRows(rows)
  }

  onSearch (keyword: string) {
    this.filtering = true
    this.serachDelayFn(keyword)
  }

  onAdd (row: any) {
    this.add(row)
  }

  onCheckedChange () {
    const el = this.$refs.tree as any
    if (el) {
      this.setCheckRows(el.getCheckedNodes())
    }
  }

  onSelectedAll (node: any, selected: boolean) {
    const el = this.$refs.tree as any
    if (el) {
      setChecked(el, node)
    }

    function setChecked (el: any, node: any) {
      el.setChecked(node.data, selected, false)
      const childNodes = node?.childNodes || []
      if (childNodes.length > 0) {
        childNodes.forEach((v: any) => {
          setChecked(el, v)
        })
      }
    }
  }

  label (node: any) {
    const n = node.label
    const c = '' // node.level === 1 ? ` (${node.data.count})` : ''
    return n + c
  }

  loadFn (node: any, resolve: any) {
    if (node.level === 0) {
      queryRootTeams(this.currentSpace?.ownId).then(data => {
        resolve(data.map(v => Object.assign({ label: v.name, type: 'team', _id: `team-${v.id}`, _nodeKey: `team-${v.id}` }, v)))
      })
      // setTimeout(() => {
      //   resolve([...Array(5).keys()].map(k => ({ label: `团队${k}rfrgregregtgeregre分为而非黑未返回IE未返回IE我iiiiiii`, type: 'team', count: 5, leaf: Boolean(Math.random() > 0.5) })))
      // }, 1500)
    } else {
      Promise.all([queryTeamsByParent(node?.data?.id), queryUsersByTeam(node?.data?.id)]).then(([teams, users]) => {
        resolve([
          ...teams.map(v => Object.assign({ label: v.name, type: 'team', _id: `team-${v.id}`, _nodeKey: `team-${v.id}` }, v)),
          ...users.map(v => Object.assign({ label: v.name, type: 'user', _id: `user-${v.userId}`, _nodeKey: `team-${v.userId}-${v.id}`, leaf: true }, v))
        ])
      })
      // setTimeout(() => {
      //   resolve([...Array(5).keys()].map(k => ({ label: `用户${k}`, type: 'user', leaf: true })))
      // }, 1500)
    }
  }

  searchData (keyword: string) {
    if (!keyword) return Promise.resolve([])
    return searchTeams(this.currentSpace?.ownId, keyword).then(data => {
      const ret = (data || []).map(v => Object.assign(v, { label: v.name, type: 'team', _id: `team-${v.id}` }))
      if (ret.length < 10) {
        return searchEntUsers(this.currentSpace?.ownId, keyword).then(users => {
          const r = (users || []).map(v => Object.assign(v, { label: v.name, type: 'user', _id: `user-${v.userId}` }))
          return [...ret, ...r]
        })
      }
      return ret
    })
  }

  created () {
    this.serachDelayFn = debounce((keyword: string) => {
      this.filtering = true
      this.filterData = []
      this.searchData(keyword).then(data => {
        this.filterData = data || []
      }).finally(() => {
        this.filtering = false
      })
      // setTimeout(() => {
      //   this.filtering = false
      //   this.filterData = [
      //     { label: '团队ABC', type: 'team' },
      //     { label: '团队一', type: 'team' },
      //     { label: '用户ABC', type: 'user' }
      //   ]
      // }, 1500)
    }, 750)
  }

  @Watch('checkedRows') checkRowsChange () {
    if (!this.checkedRows || this.checkedRows === this.localCheckedRows) return
    const el = this.$refs.tree as any
    if (el) {
      el.setCheckedNodes(this.checkedRows || [])
    }
  }
}
</script>

<style lang="scss" module>
@import "~@/styles/vars.scss";

.container {
  height: 100%;
}

.search {
  box-sizing: border-box;
  border-bottom: solid 1px $border-split-color;
  :global {
    .el-input__inner {
      border: none;
    }
  }
}

.body {
  height: calc(100% - 40px - 2px);
  overflow: auto;
}

.tree {
  :global {
    .el-tree-node__content {
      height: 40px;
    }
  }
}

.item {
  display: flex;
  flex: 1;
  width: 0;
  height: 100%;
  align-items: center;

  &:hover {
    .action {
      opacity: 1;
    }
  }
}

.text {
  flex: 1 1 auto;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.action {
  flex: 0 0 auto;
  margin: 0 12px;
  opacity: 0;
  transition: all ease .25s;
}

.filterWrap {
  height: 100%;
}

.list {
  list-style: none;
  margin: 0;
  padding: 0;
  min-height: 100%;
}

.listItem {
  display: flex;
  height: 40px;
  align-items: center;
  padding: 0 0 0 20px;

  &:hover {
    background-color: $bg-body-color;
    .action {
      opacity: 1;
    }
  }
}
</style>
